﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Reflection;
using Peter.Common;
using Peter.Logic.Plugins;

namespace Peter.Logic
{
   /// <summary>
   /// Manages all of the plugins for peter.
   /// </summary>
   public class PluginManager : IPartImportsSatisfiedNotification
   {
      /// <summary>
      /// Gets the list of plugins.
      /// </summary>
      [ImportMany (typeof (PeterPluginBase), AllowRecomposition = true)]
      public IEnumerable<Lazy<PeterPluginBase, IPeterMetadata>> Plugins { get; private set; }

      /// <summary>
      /// Loads any available plugins.
      /// </summary>
      public void LoadPlugins ()
      {
         var catalog = new AggregateCatalog (new DirectoryCatalog (".\\plugins"),
                                             new AssemblyCatalog (Assembly.GetExecutingAssembly ()));
         var container = new CompositionContainer (catalog);
         container.ComposeParts (this);
      }

      /// <summary>
      /// Called when a part's imports have been satisfied and it is safe to use.
      /// </summary>
      public void OnImportsSatisfied ()
      {
         // TODO: Verify if plugin names are the same...
         foreach (var plugin in this.Plugins)
         {
            bool isInstalled = MainViewModel.Options.InstalledPlugins.Any (ip => ip.Name == plugin.Metadata.Name);
            if (!isInstalled)
            {
               MainViewModel.Options.InstalledPlugins.Add (new Plugin
                                                              {
                                                                 Name = plugin.Metadata.Name,
                                                                 Description = plugin.Metadata.Description,
                                                                 Author = plugin.Metadata.Author,
                                                                 Version = plugin.Metadata.Version,
                                                                 IsInstalled = true
                                                              });
               plugin.Value.Install ();
            }
         }
      }

      /// <summary>
      /// Gets the plugin with the corresponding name.
      /// </summary>
      /// <param name="pluginName">Name of plugin to get.</param>
      /// <returns>Requested plugin, null if it does not exist.</returns>
      public PeterPluginBase GetPlugin (string pluginName)
      {
         return (from plugin in Plugins
                 let name = plugin.Metadata.Name
                 where name == pluginName select plugin.Value).FirstOrDefault ();
      }
   }
}
